#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Wataplayah, a PyTeam project
# <http://code.google.com/p/wataplayah/>
# version 0.1 pre-alpha
#
# Wataplayah was coded by PyTeam <pyteam@portugal-a-programar.org / http://www.portugal-a-programar.org/forum/index.php/topic,16367.0.html> members:
# -> David Ferreira (djthyrax) <djthyrax@gmail.com>
# -> Rolando Pereira (rolando2424)
# -> Francisco Huhn (Tharis)
#
# Have any questions? Feel free to email us: pyteam@portugal-a-programar.org

# This software is licenced under GNU GENERAL PUBLIC LICENSE version 2.
# Wataplayah comes with ABSOLUTELY NO WARRANTY.
# This is free software, you are welcome to redistribute it under certain
# contitions. See LICENSE.txt for details.

import os, debug, savedebug


#TODO:
# * Create a method that returns the "bic_dict". Use the original parse_big_list
#   method. <DONE!> Make it so that it can return all the information about just
#   one channel <DONE!> Test it on the tv stations. <DONE!> Test to see if the
#    search works with non-ascii characters. <Not yet :( It seems like it's a
#   Python problem though with the encoding that Windows uses to save files.>

# CHANGELOG:
# 31/01/2008
# * Corrected a bug with list_cat and get_info_from_files, which caused it
#   to never show the lastchannel in a file (causing files with only one
#   channel to appear blank)

class Database_Fetcher_V3:
    """Database Parser, Third Version. CODENAME: Burning Binary.
    
    This is the parser for the second version of the channel database 
    created by LightMC from Portugal-a-Programar 
    ( http://www.portugal-a-programar.org )
    
    I tried to make this class as backwards compatible as possible, so
    it should be easy to upgrade from the previous parser.
    
    Just call one of the set_* method before the cats() method and you
    should be fine.
    
    When you want to use another set_* method, make sure you call the
    reset_switch() method, or else expect some weird behaviour.
    
    This class has the following methods.
    
    -------------------------------------------------------------------
    
    set_tv_by_country()
    set_tv_by_category()
    set_radio_portugal()
    set_radio_greece()
    One of this 4 methods has to be called before calling any of the next
    method (except the reset_switch() method, which will be explained later).
    
    -------------------------------------------------------------------
    
    cats() - Returns the name of the files in the folder. The folder depends
    on the set_* method that is active when you call it.
    If you called "set_tv_by_country", then the folder will be 
    "./RTDB_original_v2.0/tvs/by_country", if it's set_tv_by_category,
    then the folder will be "./RTDB_original_v2.0/tvs/by_category".
    The same thing happens to the other two methods, except the folders
    are "./RTDB_original_v2.0/radios/portugal" and 
    "./RTDB_original_v2.0/radios/greece_(ellada)" respectably.
    
    -------------------------------------------------------------------
    
    list_cat(filename) - Returns a dictionary containing all the channels
    and their URLs found in the filename. You can't put the extension of the
    file in the filename, that is, use "lifestyle" and not "lifestyle.rdb"
    The syntax of the dictionary is  {"Name of the channel" : "Url to play"}
    
    -------------------------------------------------------------------
    
    get_info_from_files(filename, [channel]) - Returns a dictionary
    containing all the information available in the filename about all
    channels. If a channel is specified, it will only return the
    information found about that channel. If the channel is specified,
    but cannot be found in the filename, it returns 1.
    As with the method "list_cat", filename can't have the extension,
    that is, use "lifestyle" and not "lifestyle.rbg".
    The syntax of the dictionary is:
        [
          "Name of the channel",
          "Url to play",
          "Oficial webpage",
          "Original country",
          "Description",
          "Channel symbol",
          "FakeEnter Url (opens a certain webpage so that the channel works)"
          "Passing channel"
        ]
    I don't know exactly what the last 3 options do, for more information
    ask lightMC. (See the credits part on the README.txt file)
    
    Also, the search of the channel will not work with names that have
    characters not in the ASCII encoding (This is seen for example in
    portuguese radios or channels.
    
    -------------------------------------------------------------------
    
    reset_switch() - Just sets the values of all set_* variables to 0.
    Should be called before calling any of the set_* methods."""
    
    def __init__(self):
        """Just defines some constants and initializes the values of the
        variables that are going to be used in the set_* methods. Also
        sets the extension of the files of the database (currently, that
        is ".rdb" """
        try:
        
            #### Some Constants
            self.TV_BY_COUNTRY_FOLDER_PATH = self.__get_full_path("/RTDB_original_v2.0/tvs/by_country/")
            self.TV_BY_CATEGORY_FOLDER_PATH = self.__get_full_path("/RTDB_original_v2.0/tvs/by_category/")
            self.RADIO_PORTUGAL_FOLDER_PATH = self.__get_full_path("/RTDB_original_v2.0/radios/portugal")
            self.RADIO_GREECE_FOLDER_PATH = self.__get_full_path("/RTDB_original_v2.0/radios/greece_(ellada)")
            ####
            
            #### This values will be used to tell the cats() method what
            #### folder he should use.
            #### To change the values of these variables, use one of the
            #### set_* methods.        
            self.tv_by_country = 0
            self.tv_by_category = 0
            self.radio_portugal = 0
            self.radio_greece = 0
            
            self.ext = ".rdb" # The extension of the files, if it changes in
                              # the future, we only need to change this value.
        
        
        ### Beginning of the set_* methods (Remember, you have to call one
        ### of these before using the cats() method.
        except:
            erro=debug.debug()
            savedebug.savedebug(erro)
            
    def set_tv_by_country(self):
        try:
            """sets tv_by_country = 1"""
            self.tv_by_country = 1
        except:
            erro=debug.debug()
            savedebug.savedebug(erro)
    
    def set_tv_by_category(self):
        try:
            """sets tv_by_category = 1"""
            self.tv_by_category = 1
        except:
            erro=debug.debug()
            savedebug.savedebug(erro)
            
    def set_radio_portugal(self):
        try:
            """sets radio_portugal = 1"""
            self.radio_portugal = 1
        except:
            erro=debug.debug()
            savedebug.savedebug(erro)
            
    
    def set_radio_greece(self):
        try:
            """sets radio_greece  = 1"""
            self.radio_greece = 1
        except:
            erro=debug.debug()
            savedebug.savedebug(erro)
            
    ###
    
    
    def reset_switch(self):
        try:
            """Resets all values set by the set_* methods, that is,
            tv_by_country = 0, tv_by_category = 0, radio_portugal = 0 and
            radio_greece.
            It you want to change to another folder in the dabatase, you
            have to call this function before calling one of the set_* methods
            and the cats() method."""
            self.tv_by_country = 0
            self.tv_by_category = 0
            self.radio_portugal = 0
            self.radio_greece = 0
        except:
            erro=debug.debug()
            savedebug.savedebug(erro)
            
        

    def cats(self):    # How are you gentlemen!!
        try:
            
            """Returns the name of all the files that belong to the database
            in the folder. The folder is set depending of what set_* method
            is active.
            The "_" in the filename are replaced with " ", for a nicer
            output. It is then converted back at the list_cat() method."""
            
            if self.tv_by_country == 1:
                directory_to_search = self.TV_BY_COUNTRY_FOLDER_PATH
            elif self.tv_by_category == 1:
                directory_to_search = self.TV_BY_CATEGORY_FOLDER_PATH
            elif self.radio_portugal == 1:
                directory_to_search = self.RADIO_PORTUGAL_FOLDER_PATH
            elif self.radio_greece == 1:
                directory_to_search = self.RADIO_GREECE_FOLDER_PATH
            else:
                print "Problem found in cats function." # You are on the
                print "This shouldn't happen!"            # way to destruction.
                print "If you're the developer did you forget to call a set_* method?"
                
            
            self.categories = []
            
            for i in os.listdir(directory_to_search):
                if i[-4::] == self.ext: # If the extension of the file is
                                        # the same of the files that belong
                                        # to the database
                    
                    # So we can have a grammatically correct output. Also change
                    # the "_" with " " (it's kinda ugly in the menu a option
                    # with "_" in it :) ). Don't worry. We'll put back the "_"
                    # in the "list_cat" method.
                    #self.categories.append(i[:-4:].capitalize().replace("_", " ")) # So we can have a grammatically correct output
                    
                    # Bah, it seems it doesn't work, I forgot that I'm going to need the "real" name of the file
                    # in list_cat function. Well, it's the though that counts.
                    # You can always uncomment the previous line, if you then use the lower() method
                    # of a string. But what if the file has a uppercase letter in it name?
                    # Yeah, I though so. It's better to leave this to the program that uses
                    # this class. So we use this instead.
                    self.categories.append(i[:-4].replace("_", " "))
                    
            return self.categories     # List with the names of all files of the
                                    # right extension according to the database.

            # You have no chance to survive make your time.
        except:
            erro=debug.debug()
            savedebug.savedebug(erro)
            

        
    def list_cat(self, filename):
        try:
                
            """Returns a dictionary with the following syntax:
            { "Name of the channel" : "Url to play" }
                
            Filename is the name of the file in the database (the ones that
            appear on the return value of the cats() method.
            
            Also, it turns the " " present in the filename into "_" """
            if self.tv_by_country == 1:
                path = self.TV_BY_COUNTRY_FOLDER_PATH
            elif self.tv_by_category == 1:
                path = self.TV_BY_CATEGORY_FOLDER_PATH
            elif self.radio_portugal == 1:
                path = self.RADIO_PORTUGAL_FOLDER_PATH
            elif self.radio_greece == 1:
                path = self.RADIO_GREECE_FOLDER_PATH
            else:
                print "Problem found in list_cat function." # FIRE IN THE HOLE!
                print "This shouldn't happen!"
                print "If you're the developer did you forget to call a set_* method?"

            
            filename = filename.strip() # Just in case the user send spaces 
                                        # In the end
            filename = filename.replace(" ", "_")    # Undo what we did back at
                                                     # the "cats" method.
            lines_in_file = file(path + filename + self.ext, "r").read().replace("\r\n", "\n").replace("\r", "\n").split("\n\n")
            
            self.category = {}
        
            for tmp_channel in lines_in_file[1:int(lines_in_file[0])+1]:
                tmp_channel = tmp_channel.split("\n")
                if len(tmp_channel) != 8:     # A channel always contains
                    continue                  # 8 parameters
                elif not tmp_channel[0] != '' or not tmp_channel[1] != '':
                    continue
                else:
                    # We only need the name of that channel and the url
                    # to play. If you want the FULL information about it,
                    # please use the "get_info_from_files" method.
                    self.category[tmp_channel[0]] = tmp_channel[1]

            return self.category
        except:
            erro=debug.debug()
            savedebug.savedebug(erro)
            


    def get_info_from_files(self, filename, channel=""):
        try:
            
            """Returns a dictionary of all the information in the file
            It uses the following syntax:
            {index_number:
                [
                  "Name of the channel",
                  "Url to play",
                  "Oficial webpage",
                  "Original country",
                  "Description",
                  "Channel symbol",
                  "FakeEnter Url (opens a certain webpage so that the channel works)"
                  "Passing channel"
                ]
            }
            I don't know exactly what the last 3 options do, for more information
            ask lightMC.
            
            It a channel is specified, then it will return all the information
            about that channel, otherwise, it returns the information about
            all channels present in the file.
            
            *WARNING* The search doesn't work with channels whose name has
            characters that don't belong in the ASCII encoding. (Problems
            between the files encoding and/or the encoding of python).
            
            This method is similar to the list_cat() method.
            """
            
            if self.tv_by_country == 1:
                path = self.TV_BY_COUNTRY_FOLDER_PATH
            elif self.tv_by_category == 1:
                path = self.TV_BY_CATEGORY_FOLDER_PATH
            elif self.radio_portugal == 1:
                path = self.RADIO_PORTUGAL_FOLDER_PATH
            elif self.radio_greece == 1:
                path = self.RADIO_GREECE_FOLDER_PATH
            else:
                print "Problem found in get_info_from_files function."     # INCOMING!
                print "This shouldn't happen!"                            # TAKE COVER!
                print "If you're the developer did you forget to call a set_* method?"
            
            filename = filename.strip() # Just in case the user send spaces 
                                        # In the end
            filename = filename.replace(" ", "_")    # Undo what we did back at
                                                    # the "cats" method.

            lines_in_file = file(path + filename + self.ext, "r").read().replace("\r\n", "\n").replace("\r", "\n").split("\n\n")
            
            self.dict_channel = {}
            idx = 0

            for tmp_channel in lines_in_file[1:int(lines_in_file[0])+1]:
                tmp_channel = tmp_channel.split("\n")
                if not len(tmp_channel) != 8 or \
                   tmp_channel[0] != '' or tmp_channel[1] != '':
                    self.dict_channel[idx] = tmp_channel
                idx += 1

            if channel.strip() == "":    # Then return all information for all channels
                                # in the file
                return self.dict_channel
            else:
                for index in self.dict_channel:
                    if self.dict_channel[index][0] == channel:     # The name of the channel is
                                                                # in the position [0]
                        return self.dict_channel[index]    # Information from just
                                                        # ONE channel
                return 1 # If we didn't quit the function, that means the channel
                         # does not exist
        except:
            erro=debug.debug()
            savedebug.savedebug(erro)
            


    def __get_full_path(self, folder):
        try:
                
            """*sigh* This should be taken care of by the os.path.join, but
            it isn't...
            
            Returns the full pathname to a folder in the database.
            """
            if folder[-1] != "/":    # This is mostly a safe switch. I might forget
                folder += "/"        # to add the / on the end of the path.
            else:
                pass
            
            return os.path.join(os.getcwd()+folder)
        except:
            erro=debug.debug()
            savedebug.savedebug(erro)
            

app = Database_Fetcher_V3() # Backwards compatibility

if __name__ == "__main__":
    print "Portugal Radios!"

    app.set_radio_portugal()
    app.cats()

    for i in app.categories:
        print i
    print ""

    print "These are the channels on the vila_real file!"

    ################### One way to do it ##########################
    #channels = db.list_cat("vila_real")                          #
    #                                                              #
    #for i in channels:                                              #
    #    print "%s \n -> %s" % (i, channels[i])                      #
    ###############################################################
    
    ##### And another way (original way in the first parser. ######
    ############ Included for backwards compatibility.) ###########
    app.list_cat("vila real")                                      #
                                                                  #
    for i in app.category:                                          #
        print "%s \n -> %s" % (i, app.category[i])                  #
    ###############################################################

    print ""
    print "-"*50
    print ""
    
    # To print another thing, for example tv_by_category, first call the
    # "rest_switch" method. Then procedure as normal.
    
    app.reset_switch()
    
    print "TV by category channels!"
    
    app.set_tv_by_category()
    app.cats()
    
    for i in app.categories:
        print i
    print ""
    
    print "These are the channels on the lifestyle file!"
    
    #### For another way, to do this see the previous example
    app.list_cat("lifestyle")
    
    for i in app.category:
        print "%s \n -> %s" % (i, app.category[i])
    #####
    
    print ""
    print "-"*50
    print ""

    #### Get the full information about all the channels in one file ##
    app.get_info_from_files("lifestyle")                              #
    print app.dict_channel                                              #
    ###################################################################
    ###################### Or another way #############################
    #full_info = db.get_info_from_files("lifestyle")                  #
    #print full_info                                                  #
    ###################################################################
    
    print ""
    print "-"*50
    print ""
    
    print "Full information about the Baby TV in the lifestyle channel!"
    print ""
    ######## Get the full information about just *ONE* channel ##########
    channel_full_info = app.get_info_from_files("lifestyle", "Baby TV") #
    print channel_full_info                                                #
    #####################################################################

    ###### TO TEST THE LIST_CAT AND THE GET_INFO_FROM_FILES METHODS ####

    #print "Tv by country"
    
    #app.set_tv_by_country()
    #tmp = app.get_info_from_files("iceland")
    #print tmp
